bitkeeper revision 1.794.1.3 (405de995_4scoWE5EfQzN5TSoyS8Gw)
authoriap10@tetris.cl.cam.ac.uk <iap10@tetris.cl.cam.ac.uk>
Sun, 21 Mar 2004 19:14:29 +0000 (19:14 +0000)
committeriap10@tetris.cl.cam.ac.uk <iap10@tetris.cl.cam.ac.uk>
Sun, 21 Mar 2004 19:14:29 +0000 (19:14 +0000)
fixes plus new performance counters

xen/arch/i386/process.c
xen/arch/i386/traps.c
xen/common/memory.c
xen/common/perfc.c
xen/common/shadow.c
xen/include/xeno/perfc.h
xen/include/xeno/perfc_defn.h
xen/include/xeno/shadow.h

index 8ed1cf2dc2e1870ddfbdc97db5fcec4ce0cdf0ed..2c5380108935c09676f6ccc7dedfc74b9f9d9766 100644 (file)
@@ -290,8 +290,8 @@ void switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 
     if( next_p->mm.shadowmode )
       {
-       write_cr3_counted(pagetable_val(next_p->mm.shadowtable));
        check_pagetable( next_p->mm.pagetable, "switch" );
+       write_cr3_counted(pagetable_val(next_p->mm.shadowtable));
       }
     else
 #endif
index 717ca6d2cbd57262531784e7f488962af821a90d..eed1fb9faf330a5a3240dbc1e69d406c54476254 100644 (file)
@@ -340,15 +340,11 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
     }
 
 #ifdef CONFIG_SHADOW
-//printk("1");
-check_pagetable( current->mm.pagetable, "pre-sf" );
     if ( p->mm.shadowmode && addr < PAGE_OFFSET &&
         shadow_fault( addr, error_code ) )
       {
-       check_pagetable( current->mm.pagetable, "post-sfa" );
        return; // return true if fault was handled 
       }
-    check_pagetable( current->mm.pagetable, "post-sfb" );
 #endif
 
     if ( unlikely(!(regs->xcs & 3)) )
index e672f78fe09eae6cd7dd3274cfcf428106b5792e..f6e8155f71cd3c4c0193c4314b864f8eb16249f4 100644 (file)
@@ -764,19 +764,26 @@ void free_page_type(struct pfn_info *page, unsigned int type)
     switch ( type )
     {
     case PGT_l1_page_table:
-        return free_l1_table(page);
-    case PGT_l2_page_table:
-        return free_l2_table(page);
-    default:
-        BUG();
-    }
+        free_l1_table(page);
+#ifdef CONFIG_SHADOW
+       // assume we're in shadow mode if PSH_shadowed set
+       if ( current->mm.shadowmode && page->shadow_and_flags & PSH_shadowed )
+           unshadow_table( page-frame_table, type );
+#endif
+       return;
 
+    case PGT_l2_page_table:
+        free_l2_table(page);
 #ifdef CONFIG_SHADOW
-    // assume we're in shadow mode if PSH_shadowed set
-    if ( page->shadow_and_flags & PSH_shadowed )
-      unshadow_table( page-frame_table );
+       // assume we're in shadow mode if PSH_shadowed set
+       if ( current->mm.shadowmode && page->shadow_and_flags & PSH_shadowed )
+           unshadow_table( page-frame_table, type );
 #endif
+       return;
 
+    default:
+        BUG();
+    }
 }
 
 
@@ -846,7 +853,17 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
              shadow_mk_pagetable(pfn << PAGE_SHIFT, current->mm.shadowmode);
 #endif
             invalidate_shadow_ldt();
-            percpu_info[cpu].deferred_ops |= DOP_FLUSH_TLB;
+
+            percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB;
+#ifdef CONFIG_SHADOW
+            if ( unlikely(current->mm.shadowmode) )
+           {
+                check_pagetable( current->mm.pagetable, "pre-stlb-flush" );
+               write_cr3_counted(pagetable_val(current->mm.shadowtable));
+            }
+            else
+#endif   
+               write_cr3_counted(pagetable_val(current->mm.pagetable));
         }
         else
         {
@@ -1082,7 +1099,10 @@ check_pagetable( current->mm.pagetable, "mmu" ); // XXX XXX XXX XXX XXX
     {
 #ifdef CONFIG_SHADOW
         if ( unlikely(current->mm.shadowmode) )
-         write_cr3_counted(pagetable_val(current->mm.shadowtable));
+       {
+            check_pagetable( current->mm.pagetable, "pre-stlb-flush" );
+           write_cr3_counted(pagetable_val(current->mm.shadowtable));
+        }
         else
 #endif   
          write_cr3_counted(pagetable_val(current->mm.pagetable));
index 00d0505503006b485df7e68e9d24ba2b46cc8191..af9abbb67c7bc6a61d78060ebe14a63d670a93c7 100644 (file)
@@ -8,12 +8,20 @@
 #undef  PERFCOUNTER
 #undef  PERFCOUNTER_CPU
 #undef  PERFCOUNTER_ARRAY
+#undef  PERFSTATUS
+#undef  PERFSTATUS_CPU
+#undef  PERFSTATUS_ARRAY
 #define PERFCOUNTER( var, name )              { name, TYPE_SINGLE, 0 },
 #define PERFCOUNTER_CPU( var, name )          { name, TYPE_CPU,    0 },
 #define PERFCOUNTER_ARRAY( var, name, size )  { name, TYPE_ARRAY,  size },
+#define PERFSTATUS( var, name )               { name, TYPE_S_SINGLE, 0 },
+#define PERFSTATUS_CPU( var, name )           { name, TYPE_S_CPU,    0 },
+#define PERFSTATUS_ARRAY( var, name, size )   { name, TYPE_S_ARRAY,  size },
 static struct {
     char *name;
-    enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY } type;
+    enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY,
+          TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY
+    } type;
     int nr_elements;
 } perfc_info[] = {
 #include <xeno/perfc_defn.h>
@@ -38,10 +46,12 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs)
         switch ( perfc_info[i].type )
         {
         case TYPE_SINGLE:
+        case TYPE_S_SINGLE:
             printk("TOTAL[%10d]", atomic_read(&counters[0]));
             counters += 1;
             break;
         case TYPE_CPU:
+        case TYPE_S_CPU:
             for ( j = sum = 0; j < smp_num_cpus; j++ )
                 sum += atomic_read(&counters[j]);
             printk("TOTAL[%10d]  ", sum);
@@ -50,6 +60,7 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs)
             counters += NR_CPUS;
             break;
         case TYPE_ARRAY:
+        case TYPE_S_ARRAY:
             for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ )
                 sum += atomic_read(&counters[j]);
             printk("TOTAL[%10d]  ", sum);
@@ -64,9 +75,37 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs)
 
 void perfc_reset(u_char key, void *dev_id, struct pt_regs *regs)
 {
+    int i, j, sum;
     s_time_t now = NOW();
+    atomic_t *counters = (atomic_t *)&perfcounters;
+
     printk("Xen performance counters RESET (now = 0x%08X:%08X)\n",
            (u32)(now>>32), (u32)now);
-    memset(&perfcounters, 0, sizeof(perfcounters));
+
+    // leave STATUS counters alone -- don't reset
+
+    for ( i = 0; i < NR_PERFCTRS; i++ ) 
+    {
+        switch ( perfc_info[i].type )
+        {
+        case TYPE_SINGLE:
+           atomic_set(&counters[0],0);
+        case TYPE_S_SINGLE:
+            counters += 1;
+            break;
+        case TYPE_CPU:
+            for ( j = sum = 0; j < smp_num_cpus; j++ )
+               atomic_set(&counters[j],0);
+        case TYPE_S_CPU:
+            counters += NR_CPUS;
+            break;
+        case TYPE_ARRAY:
+            for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ )
+               atomic_set(&counters[j],0);
+        case TYPE_S_ARRAY:
+            counters += j;
+            break;
+        }
+    }
 }
 
index f43968018f8ff104d6711aeb920ec93ccbfc472f..a0df57d8f116284b4987c27e7bc9888de98b1a07 100644 (file)
@@ -10,7 +10,7 @@
 #ifdef CONFIG_SHADOW
 
 
-#if 1
+#if SHADOW_DEBUG
 #define MEM_VLOG(_f, _a...)                             \
   printk("DOM%llu: (file=shadow.c, line=%d) " _f "\n", \
          current->domain , __LINE__ , ## _a )
@@ -63,11 +63,14 @@ pagetable_t shadow_mk_pagetable( unsigned long gptbase,
        return mk_pagetable(spfn << PAGE_SHIFT);
 }
 
-void unshadow_table( unsigned long gpfn )
+void unshadow_table( unsigned long gpfn, unsigned int type )
 {
        unsigned long spfn;
 
-MEM_VLOG("unshadow_table %08lx\n", gpfn );
+    MEM_VLOG("unshadow_table type=%08x gpfn=%08lx, spfn=%08lx",
+                type,
+                gpfn,
+                frame_table[gpfn].shadow_and_flags & PSH_pfn_mask );
 
        perfc_incrc(unshadow_table_count);
 
@@ -80,8 +83,8 @@ MEM_VLOG("unshadow_table %08lx\n", gpfn );
        frame_table[gpfn].shadow_and_flags=0;
        frame_table[spfn].shadow_and_flags=0;
 
-#ifdef DEBUG
-       { // XXX delete me!
+#if 0 // XXX leave as might be useful for later debugging
+       { 
                int i;
                unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT );
 
@@ -93,7 +96,21 @@ MEM_VLOG("unshadow_table %08lx\n", gpfn );
        }
 #endif
 
-       free_domain_page( &frame_table[spfn] );
+       if (type == PGT_l1_page_table)
+               perfc_decr(shadow_l1_pages);
+    else
+               perfc_decr(shadow_l2_pages);
+
+       //free_domain_page( &frame_table[spfn] );
+
+       {
+    unsigned long flags;
+    spin_lock_irqsave(&free_list_lock, flags);
+    list_add(&frame_table[spfn].list, &free_list);
+    free_pfns++;
+    spin_unlock_irqrestore(&free_list_lock, flags);
+       }
+
 }
 
 
@@ -107,6 +124,7 @@ unsigned long shadow_l2_table( unsigned long gpfn )
        MEM_VVLOG("shadow_l2_table( %08lx )",gpfn);
 
        perfc_incrc(shadow_l2_table_count);
+       perfc_incr(shadow_l2_pages);
 
     // XXX in future, worry about racing in SMP guests 
     //      -- use cmpxchg with PSH_pending flag to show progress (and spin)
@@ -198,6 +216,8 @@ int shadow_fault( unsigned long va, long error_code )
 
        MEM_VVLOG("shadow_fault( va=%08lx, code=%ld )", va, error_code );
 
+    check_pagetable( current->mm.pagetable, "pre-sf" );
+
        if ( unlikely(__get_user(gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) )
        {
                MEM_VVLOG("shadow_fault - EXIT: read gpte faulted" );
@@ -250,7 +270,7 @@ int shadow_fault( unsigned long va, long error_code )
                unsigned long gpde, spde, gl1pfn, sl1pfn;
 
         MEM_VVLOG("3: not shadowed or l2 insufficient gpte=%08lx  spte=%08lx",gpte,spte );
+
         gpde = l2_pgentry_val(linear_l2_table[va>>L2_PAGETABLE_SHIFT]);
 
         gl1pfn = gpde>>PAGE_SHIFT;
@@ -266,6 +286,7 @@ int shadow_fault( unsigned long va, long error_code )
 
             MEM_VVLOG("4a: l1 not shadowed ( %08lx )",sl1pfn);
                perfc_incrc(shadow_l1_table_count);
+               perfc_incr(shadow_l1_pages);
 
             sl1pfn_info->shadow_and_flags = PSH_shadow | gl1pfn;
             frame_table[gl1pfn].shadow_and_flags = PSH_shadowed | sl1pfn;
@@ -337,6 +358,8 @@ int shadow_fault( unsigned long va, long error_code )
        
     perfc_incrc(shadow_fixup_count);
 
+    check_pagetable( current->mm.pagetable, "post-sf" );
+
     return 1; // let's try the faulting instruction again...
 
 }
@@ -521,9 +544,11 @@ int check_l1_table( unsigned long va, unsigned long g2, unsigned long s2 )
        int j;
        unsigned long *gpl1e, *spl1e;
 
-       gpl1e = (unsigned long *) &(linear_pg_table[ va>>PAGE_SHIFT]);
-       spl1e = (unsigned long *) &(shadow_linear_pg_table[ va>>PAGE_SHIFT]);
+       //gpl1e = (unsigned long *) &(linear_pg_table[ va>>PAGE_SHIFT]);
+       //spl1e = (unsigned long *) &(shadow_linear_pg_table[ va>>PAGE_SHIFT]);
 
+       gpl1e = map_domain_mem( g2<<PAGE_SHIFT );
+       spl1e = map_domain_mem( s2<<PAGE_SHIFT );
 
        for ( j = 0; j < ENTRIES_PER_L1_PAGETABLE; j++ )
        {
@@ -532,12 +557,15 @@ int check_l1_table( unsigned long va, unsigned long g2, unsigned long s2 )
                
                check_pte( gpte, spte, 1, j );
        }
+       
+       unmap_domain_mem( spl1e );
+       unmap_domain_mem( gpl1e );
 
        return 1;
 }
 
 #define FAILPT(_f, _a...)                             \
-{printk("XXX FAILPT" _f "\n", ## _a ); BUG();}
+{printk("XXX FAIL %s-PT" _f "\n", s, ## _a ); BUG();}
 
 int check_pagetable( pagetable_t pt, char *s )
 {
@@ -546,8 +574,6 @@ int check_pagetable( pagetable_t pt, char *s )
        int i;
        l2_pgentry_t *gpl2e, *spl2e;
 
-return 1;
-
        sh_check_name = s;
 
     MEM_VVLOG("%s-PT Audit",s);
@@ -573,10 +599,41 @@ return 1;
        if ( ! frame_table[spfn].shadow_and_flags == (PSH_shadow | gpfn) )
                FAILPT("ptbase shadow inconsistent2");
 
+       gpl2e = (l2_pgentry_t *) map_domain_mem( gpfn << PAGE_SHIFT );
+       spl2e = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT );
+
+       //ipl2e = (l2_pgentry_t *) map_domain_mem( spfn << PAGE_SHIFT );
+
+
+       if ( memcmp( &spl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
+                       &gpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 
+                       ((SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT))-DOMAIN_ENTRIES_PER_L2_PAGETABLE)
+                       * sizeof(l2_pgentry_t)) )
+       {
+               printk("gpfn=%08lx spfn=%08lx\n", gpfn, spfn);
+               for (i=DOMAIN_ENTRIES_PER_L2_PAGETABLE; 
+                        i<(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT));
+                        i++ )
+                       printk("+++ (%d) %08lx %08lx\n",i,
+                                  l2_pgentry_val(gpl2e[i]), l2_pgentry_val(spl2e[i]) );
+               FAILPT("hypervisor entries inconsistent");
+       }
+
+       if ( (l2_pgentry_val(spl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) != 
+                 l2_pgentry_val(gpl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT])) )
+               FAILPT("hypervisor linear map inconsistent");
+
+       if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) != 
+                 ((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) )
+               FAILPT("hypervisor shadow linear map inconsistent %08lx %08lx",
+                          l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]),
+                                         (spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR
+                          );
+
+       if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) !=
+                 ((__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | __PAGE_HYPERVISOR))) )
+               FAILPT("hypervisor per-domain map inconsistent");
 
-       // use the linear map to get a pointer to the L2
-       gpl2e = (l2_pgentry_t *) &(linear_l2_table[0]);
-       spl2e = (l2_pgentry_t *) &(shadow_linear_l2_table[0]);
 
        // check the whole L2
        for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
@@ -601,6 +658,8 @@ return 1;
 
        }
 
+       unmap_domain_mem( spl2e );
+       unmap_domain_mem( gpl2e );
 
        MEM_VVLOG("PT verified : l2_present = %d, l1_present = %d\n",
                   sh_l2_present, sh_l1_present );
index 9ea244b3b84f91165a286928fa39ac30160ffb7d..abb36c7b1e489cfa129a068cf9c13aa7194d2ab3 100644 (file)
  * PERFCOUNTER_CPU (counter, string, size)    define a counter per CPU
  * PERFCOUNTER_ARRY (counter, string, size)   define an array of counters
  * 
+ * unlike "COUNTERS", "STATUS" variables DO NOT RESET
+ * PERFSTATUS (counter, string)               define a new performance stauts
+ * PERFSTATUS_CPU (counter, string, size)     define a status var per CPU
+ * PERFSTATUS_ARRY (counter, string, size)    define an array of status vars
+ * 
  * unsigned long perfc_value  (counter)        get value of a counter  
  * unsigned long perfc_valuec (counter)        get value of a per CPU counter
  * unsigned long perfc_valuea (counter, index) get value of an array counter
   atomic_t var[NR_CPUS];
 #define PERFCOUNTER_ARRAY( var, name, size ) \
   atomic_t var[size];
+#define PERFSTATUS( var, name ) \
+  atomic_t var[1];
+#define PERFSTATUS_CPU( var, name ) \
+  atomic_t var[NR_CPUS];
+#define PERFSTATUS_ARRAY( var, name, size ) \
+  atomic_t var[size];
 
 struct perfcounter_t 
 {
@@ -47,6 +58,7 @@ extern struct perfcounter_t perfcounters;
 #define perfc_setc(x,v)   atomic_set(&perfcounters.x[smp_processor_id()], v)
 #define perfc_seta(x,y,v) atomic_set(&perfcounters.x[y], v)
 #define perfc_incr(x)     atomic_inc(&perfcounters.x[0])
+#define perfc_decr(x)     atomic_dec(&perfcounters.x[0])
 #define perfc_incrc(x)    atomic_inc(&perfcounters.x[smp_processor_id()])
 #define perfc_incra(x,y)  atomic_inc(&perfcounters.x[y])
 #define perfc_add(x,y)    atomic_add((y), &perfcounters.x[0])
index 0475b6371ec8a6f66e8db68617a54c1b97e3ca20..bf06719e355e39b58d9fce5b07e6b33e19159a4f 100644 (file)
@@ -30,4 +30,6 @@ PERFCOUNTER_CPU( unshadow_table_count, "unshadow_table count" )
 PERFCOUNTER_CPU( shadow_fixup_count, "shadow_fixup count" )
 PERFCOUNTER_CPU( shadow_update_va_fail, "shadow_update_va_fail" )
 
-
+/* STATUS counters do not reset when 'P' is hit */
+PERFSTATUS( shadow_l2_pages, "current # shadow L2 pages" )
+PERFSTATUS( shadow_l1_pages, "current # shadow L1 pages" )
index dca0126784ec1fbfb8a3b9d10ea7fb1ca1fa8555..7034081b48f09035bb5e321e374c32ef224da442 100644 (file)
@@ -25,7 +25,7 @@
 #define shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START+(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT))))
 
 extern pagetable_t shadow_mk_pagetable( unsigned long gptbase, unsigned int shadowmode );
-extern void unshadow_table( unsigned long gpfn );
+extern void unshadow_table( unsigned long gpfn, unsigned int type );
 extern unsigned long shadow_l2_table( unsigned long gpfn );
 extern int shadow_fault( unsigned long va, long error_code );
 extern void shadow_l1_normal_pt_update( unsigned long pa, unsigned long gpte, 
@@ -37,6 +37,8 @@ extern void shadow_l2_normal_pt_update( unsigned long pa, unsigned long gpte );
 #define SHADOW_DEBUG 0
 #define SHADOW_OPTIMISE 1
 
+#endif // end of CONFIG_SHADOW
+
 #if SHADOW_DEBUG
 extern int check_pagetable( pagetable_t pt, char *s );
 #else
@@ -44,5 +46,6 @@ extern int check_pagetable( pagetable_t pt, char *s );
 #endif
 
 
-#endif
+
+
 #endif